package com.suiwei.advanced.collection;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;

//配合Lambda表达式，简化集合和数组的操作
public class StreamDemo {
    //获取Stream流
    @Test
    void getStream(){
        //单列集合通过stream()方法直接获取
        List<String> list  = new ArrayList<>();
        list.add("tom");
        list.stream();

        Set<String> set = new HashSet<>();
        set.add("tom");
        set.stream();

        //双列集合，间接获取
        Map<String,String> map = new HashMap<>();
        map.put("1","tom");
        map.entrySet().stream();

        //数组，借助数组工具类
        int[] arr ={1,2,3};
        Arrays.stream(arr);

        //零散的数据，Stream类的of方法
        Stream.of(1,2,3);

    }
    //Stream流操作
    //中间方法：返回值是Stream对象，可以继续操作，支持链式编程；filter、limit、skip、concat、distinct
    //终结方法：返回值不再是Stream对象，流会关闭；forEach、count、collect
    @Test
    void operateStream(){
        List<String> list  = new ArrayList<>();
        list.add("张三");
        list.add("李三");
        list.add("张四五");
        list.add("张三丰");
        //匿名内部类写法
        list.stream()
            .filter(
                new Predicate<String>() {
                  @Override
                  public boolean test(String s) {
                    return s.startsWith("张");
                  }
                })
            .forEach(s -> System.out.println(s));

        // lambda改造
        //filter：过滤
        list.stream().filter(s -> s.startsWith("李")).forEach(s -> System.out.println(s));
        // limit：获取前几个元素
        list.stream().limit(2).forEach(s -> System.out.println(s));
        //skip：跳过前几个元素
        list.stream().skip(2).forEach(s -> System.out.println(s));
        //concat：合并2个流
        Stream<String> limit = list.stream().limit(2);
        Stream<String> skip = list.stream().skip(2);
        Stream.concat(limit, skip).forEach(s -> System.out.println(s));
        // distinct：去重（依赖equals和hashcode方法）
        list.stream().distinct().forEach(s -> System.out.println(s));
        //如果流对象被消费过，就不允许再次使用了
        skip.distinct();// stream has already been operated upon or closed
        //count：流中元素的数量
        skip.count();

        //收集操作：Stream流操作，不会修改数据源，把Stream流操作后的结果转回到集合；collect
        //Collectors.toList()、Collectors.toSet()、Collectors.toMap()
        List<Integer> collect = Stream.of(1, 2, 3, 4, 5).filter(s -> s % 2 == 0).collect(Collectors.toList());
        Set<Integer> collect1 = Stream.of(1, 2, 3).filter(s -> s > 2).collect(Collectors.toSet());

        Map<Integer,String> map = new HashMap<>();
        map.put(1,"tom");
        map.put(2,"Jerry");
        Set<Map.Entry<Integer, String>> entries = map.entrySet();
        //lambda 写法
        Map<Integer, String> collect2 = entries.stream().filter(en -> en.getKey() < 2).collect(Collectors.toMap(
                entry -> entry.getKey(), entry -> entry.getValue()
        ));
        //方法引用 写法；两个冒号 :: 是方法引用操作符，是java8引入的一个语法糖，用来更简洁地代替 Lambda 表达式
        //语法糖：写法更简单，功能不改变；你可以理解为：“甜一点的语法”
        //类型::实例方法：“让某个对象去调用这个方法”。这个“某个对象”就是方法引用执行时上下文中的“当前元素”
        Map<Integer, String> collect3 = entries.stream().filter(en -> en.getKey() < 2).collect(Collectors.toMap(
             Map.Entry::getKey , Map.Entry::getValue
        ));

    }


}
